import os
import logging
from minio import Minio
from minio.error import S3Error
from urllib.parse import urlparse
import time

logger = logging.getLogger('minio_manager')

class MinIOManager:
    """MinIO对象存储管理器"""
    
    def __init__(self, endpoint='36.111.80.114:9000', access_key='minio_A7wZ7x', secret_key='minio_ztnAMF', bucket_name='sound-record'):
        """
        初始化MinIO客户端
        
        Args:
            endpoint: MinIO服务端点
            access_key: 访问密钥
            secret_key: 秘密密钥
            bucket_name: 存储桶名称
        """
        self.endpoint = endpoint
        self.access_key = access_key
        self.secret_key = secret_key
        self.bucket_name = bucket_name
        
        # 创建MinIO客户端
        self.client = Minio(
            endpoint,
            access_key=access_key,
            secret_key=secret_key,
            secure=False  # 使用HTTP而不是HTTPS
        )
        
        # 确保存储桶存在
        self._ensure_bucket_exists()
    
    def _ensure_bucket_exists(self):
        """确保存储桶存在，如果不存在则创建"""
        try:
            if not self.client.bucket_exists(self.bucket_name):
                self.client.make_bucket(self.bucket_name)
                logger.info(f"创建存储桶: {self.bucket_name}")
            else:
                logger.debug(f"存储桶已存在: {self.bucket_name}")
        except S3Error as e:
            logger.error(f"创建存储桶失败: {str(e)}")
            raise
    
    def upload_file(self, file_path, object_name=None):
        """
        上传文件到MinIO
        
        Args:
            file_path: 本地文件路径
            object_name: 对象名称（可选，如果不提供则使用文件名）
            
        Returns:
            str: 上传成功后的对象URL，失败返回None
        """
        try:
            if not os.path.exists(file_path):
                logger.error(f"文件不存在: {file_path}")
                return None
            
            # 如果没有指定对象名称，使用文件名
            if not object_name:
                object_name = os.path.basename(file_path)
            
            # 添加时间戳前缀避免文件名冲突
            timestamp = int(time.time())
            name, ext = os.path.splitext(object_name)
            object_name = f"{name}{ext}"
            
            logger.info(f"开始上传文件到MinIO: {file_path} -> {object_name}")
            
            # 上传文件
            self.client.fput_object(
                bucket_name=self.bucket_name,
                object_name=object_name,
                file_path=file_path
            )
            
            # 生成访问URL
            url = f"http://{self.endpoint}/{self.bucket_name}/{object_name}"
            logger.info(f"文件上传成功: {url}")
            
            return url
            
        except S3Error as e:
            logger.error(f"MinIO上传失败: {str(e)}")
            return None
        except Exception as e:
            logger.error(f"上传文件时发生错误: {str(e)}")
            return None
    
    def upload_file_data(self, file_data, object_name, content_type='application/octet-stream'):
        """
        上传文件数据到MinIO
        
        Args:
            file_data: 文件数据（字节）
            object_name: 对象名称
            content_type: 内容类型
            
        Returns:
            str: 上传成功后的对象URL，失败返回None
        """
        try:
            # 添加时间戳前缀避免文件名冲突
            timestamp = int(time.time())
            name, ext = os.path.splitext(object_name)
            object_name = f"{timestamp}_{name}{ext}"
            
            logger.info(f"开始上传文件数据到MinIO: {object_name}")
            
            # 上传文件数据
            from io import BytesIO
            data_stream = BytesIO(file_data)
            
            self.client.put_object(
                bucket_name=self.bucket_name,
                object_name=object_name,
                data=data_stream,
                length=len(file_data),
                content_type=content_type
            )
            
            # 生成访问URL
            url = f"http://{self.endpoint}/{self.bucket_name}/{object_name}"
            logger.info(f"文件数据上传成功: {url}")
            
            return url
            
        except S3Error as e:
            logger.error(f"MinIO上传失败: {str(e)}")
            return None
        except Exception as e:
            logger.error(f"上传文件数据时发生错误: {str(e)}")
            return None
    
    def delete_file(self, object_name):
        """
        从MinIO删除文件
        
        Args:
            object_name: 对象名称
            
        Returns:
            bool: 删除成功返回True，失败返回False
        """
        try:
            self.client.remove_object(self.bucket_name, object_name)
            logger.info(f"文件删除成功: {object_name}")
            return True
        except S3Error as e:
            logger.error(f"MinIO删除失败: {str(e)}")
            return False
        except Exception as e:
            logger.error(f"删除文件时发生错误: {str(e)}")
            return False
    
    def get_file_url(self, object_name):
        """
        获取文件的访问URL
        
        Args:
            object_name: 对象名称
            
        Returns:
            str: 文件访问URL
        """
        return f"http://{self.endpoint}/{self.bucket_name}/{object_name}"
    
    def list_files(self, prefix=None):
        """
        列出存储桶中的文件
        
        Args:
            prefix: 文件名前缀过滤
            
        Returns:
            list: 文件对象列表
        """
        try:
            objects = self.client.list_objects(self.bucket_name, prefix=prefix)
            return list(objects)
        except S3Error as e:
            logger.error(f"列出文件失败: {str(e)}")
            return []
        except Exception as e:
            logger.error(f"列出文件时发生错误: {str(e)}")
            return []
    
    def file_exists(self, object_name):
        """
        检查文件是否存在
        
        Args:
            object_name: 对象名称
            
        Returns:
            bool: 文件存在返回True，不存在返回False
        """
        try:
            self.client.stat_object(self.bucket_name, object_name)
            return True
        except S3Error:
            return False
        except Exception as e:
            logger.error(f"检查文件存在性时发生错误: {str(e)}")
            return False

# 创建全局MinIO管理器实例
minio_manager = MinIOManager()



